import javalang
import json
import os


def parse_java_file(file_path):
    with open(file_path, 'r', encoding='utf-8') as file:
        java_code = file.read()

    tree = javalang.parse.parse(java_code)

    class_info = {
        'class_name': None,
        'extends': None,
        'implements': [],
        'fields': [],
        'methods': [],
    }

    for path, node in tree:
        if isinstance(node, javalang.tree.ClassDeclaration):
            class_info['class_name'] = node.name
            class_info['extends'] = node.extends.name if node.extends else None
            class_info['implements'] = [imp.name for imp in (node.implements or [])]
        elif isinstance(node, javalang.tree.FieldDeclaration):
            for variable_declarator in node.declarators:
                modifiers = [str(modifier) for modifier in node.modifiers]
                class_info['fields'].append({
                    'name': variable_declarator.name,
                    'type': str(node.type),
                    'modifiers': modifiers
                })
        elif isinstance(node, javalang.tree.MethodDeclaration):
            method_info = {
                'name': node.name,
                'return_type': str(node.return_type),
                'parameters': [{'name': param.name, 'type': str(param.type)} for param in node.parameters],
                'modifiers': [str(modifier) for modifier in node.modifiers],
                'body': parse_method_body(node.body)
            }

            class_info['methods'].append(method_info)

    return class_info


def parse_method_body(method_body):
    method_info = {
        'variables': [],
        'method_calls': [],
        'if_statements': [],
        'while_loops': [],
        'for_loops': [],
        'statements': []
    }

    for node in method_body:
        if isinstance(node, javalang.tree.LocalVariableDeclaration):
            for declarator in node.declarators:
                variable_info = {
                    'name': declarator.name,
                    'type': str(node.type),
                    'modifiers': [str(modifier) for modifier in node.modifiers]
                }
                method_info['variables'].append(variable_info)
        elif isinstance(node, javalang.tree.MethodInvocation):
            method_info['method_calls'].append({
                'name': node.member,
                'arguments': [str(arg) for arg in node.arguments]
            })
        elif isinstance(node, javalang.tree.IfStatement):
            if_info = {
                'condition': str(node.condition),
                'then_statement': parse_method_body(node.then_statement),
                'else_statement': parse_method_body(node.else_statement) if node.else_statement else None
            }
            method_info['if_statements'].append(if_info)
        elif isinstance(node, javalang.tree.WhileStatement):
            while_info = {
                'condition': str(node.condition),
                'body': parse_method_body(node.body)
            }
            method_info['while_loops'].append(while_info)
        elif isinstance(node, javalang.tree.ForStatement):
            for_info = {
                'init': parse_method_body(node.init),
                'condition': str(node.condition),
                'update': parse_method_body(node.update),
                'body': parse_method_body(node.body)
            }
            method_info['for_loops'].append(for_info)
        else:
            method_info['statements'].append(str(node))

    return method_info


def parse_and_save_to_json(input_folder, output_json):
    result_data = []
    for root, dirs, files in os.walk(input_folder):
        for file in files:
            if file.endswith('.java'):
                file_path = os.path.join(root, file)
                class_info = parse_java_file(file_path)
                result_data.append(class_info)

    os.chmod(output_json, 0o755)
    with open(output_json, 'w', encoding='utf-8') as json_file:
        json.dump(result_data, json_file, indent=2)


if __name__ == "__main__":
    input_folder_path = 'D:\\data\\doSelft\\Navigation\\temp'
    output_json_path = 'D:\\data\\doSelft\\Navigation\\temp\\json\\output.json'

    parse_and_save_to_json(input_folder_path, output_json_path)
